﻿<template>
  <l-panel class="learun-bom-page" v-show="!lr_loadPage">
    <template #title>
      <div>{{ $t("产品BOM管理") }}</div>
      <div>
        <el-row :gutter="8">
          <el-col :span="19">
            <el-input
              :placeholder="$t('please enter关键字')"
              @keyup.enter.native="handleSearch"
              v-model="searchWord"
              size="mini"
            >
              <el-button
                @click="handleSearch"
                slot="append"
                icon="el-icon-search"
              ></el-button>
            </el-input>
          </el-col>
          <el-col :span="4">
            <l-tool-btns :hasAdd="false" />
          </el-col>
        </el-row>
      </div>
    </template>
    <l-layout :leftMove="false" :topMove="false" :left="340" :top="148">
      <template #left>
        <l-panel style="padding-right: 4px">
          <template #toolLeft>
            <div class="flex" style="padding-right: 8px">
              <el-button type="primary" size="mini" @click="importProduct"
                >导入产品BOM</el-button
              >
              <el-button type="warning" size="mini" @click="exportProduct"
                >导出产品BOM</el-button
              >
              <el-button type="primary" size="mini" @click="handleAdd(false)"
                >Add</el-button
              >
            </div>
          </template>

          <el-tree
            ref="tree"
            :data="data"
            class="learun-tree"
            :props="defaultProps"
            node-key="id"
            highlight-current
            @node-click="handleNodeClick"
            :load="loadNode"
            lazy
            v-if="isTree"
            :expand-on-click-node="false"
          >
            <span class="lr-tree-node" slot-scope="{ node, data }">
              {{
                data.f_EnabledMark == 1
                  ? `【${$t("禁用")}】`
                  : "" + $t(node.label)
              }}
            </span>
          </el-tree>
        </l-panel>
      </template>

      <template #top>
        <l-panel
          title="当前物料信息"
          style="padding-left: 0px; padding-bottom: 0px"
        >
          <l-table :columns="columns" :dataSource="currentTableData">
            <template v-slot:f_Count> 1 </template>
            <l-table-btns
              :btns="tableBtns"
              @click="lr_handleTableBtnClick"
            ></l-table-btns>
          </l-table>
        </l-panel>
      </template>

      <l-panel style="padding-left: 0px; padding-top: 0px">
        <template #title>
          <div>{{ $t("子级物料信息") }}</div>
            <l-tool-btns
              v-if="currentTableData.length > 0"
              :hasRefresh="false"
              @click="handleAdd(true)"
            />
        </template>

        <l-table
          ref="mainTable"
          :columns="columns"
          :dataSource="tableData"
          rowKey="f_Id"
          :lazy="true"
          :load="loadTreeTable"
        >
          <l-table-btns :btns="sonTableBtns" @click="lr_handleTableBtnClick" />
        </l-table>
      </l-panel>

      <!--表单(物料)-->
      <l-dialog
        :title="$t(formTitle)"
        :visible.sync="formVisible"
        :height="432"
        :width="500"
        @ok="handleSave"
        @close="handleCloseForm"
        @opened="handleOpenedForm"
      >
        <my-form :pid="formPid" :isChild="formIsChild" ref="form"></my-form>
      </l-dialog>
    </l-layout>

    <l-excel-import
      title="BOM导入"
      :excelAreas="excelAreas"
      classname="erpBomImport"
      :visible.sync="excelImportVisible"
    />
  </l-panel>
</template>

<script>
import MyForm from "./form"; // 物料
const api = window.$api.erpcase.bom;

export default {
  components: {
    MyForm,
  },
  data() {
    return {
      lr_isPage: true,
      moduleCode: "ERP_Bom",

      // query参数
      searchWord: "",
      isTree: true,

      // 当前物料数据
      currentTableData: [],

      // 表格参数
      tableData: [],
      columns: [
        {
          label: "物料编号",
          prop: "f_Number",
          minWidth: 160,
          align: "left",
        },
        {
          label: "物料名称",
          prop: "f_Name",
          minWidth: 120,
          align: "left",
        },
        {
          label: "物料规格",
          prop: "f_Model",
          width: 120,
          align: "left",
        },
        {
          label: "物料类别",
          prop: "f_Type",
          width: 120,
          align: "left",
          dataType: "dataSource",
          dataCode: "ERP_MaterialClasses",
          valueKey: "f_id",
          labelKey: "f_type",
        },
        {
          label: "数量",
          prop: "f_Count",
          width: 80,
          align: "center",
        },
        {
          label: "单位",
          prop: "f_Unit",
          width: 80,
          align: "center",
          dataType: "dataSource",
          dataCode: "ERP_Unit",
          valueKey: "f_id",
          labelKey: "f_name",
        },
        {
          label: "物料属性",
          prop: "f_Property",
          width: 80,
          align: "left",
          dataType: "dataSource",
          dataCode: "ERP_MaterialProp",
          valueKey: "f_id",
          labelKey: "f_type",
        },
      ],
      // 当前物料的操作按钮
      tableBtns: [
        { prop: "Edit", label: "Edit",width:40 },
        { prop: "Delete", label: "Delete",width:40 },
      ],

      // 表单参数
      formVisible: false,
      formTitle: "",
      formEditRow: null,
      formEdit: true,
      formPid: "",
      formIsChild: false,

      // 子级物料的操作按钮
      sonTableBtns: [
        { prop: "SonEdit", label: "Edit",width:40 },
        { prop: "SonDelete", label: "Delete",width:40 },
      ],

      // 这是左侧的树型选择数据
      data: [],
      treeChildMap: {},
      treeMap: {},

      defaultProps: {
        children: "children",
        label: "f_Name",
        isLeaf: "leaf",
      },

      excelImportVisible: false,
      excelAreas: [
        {
          type: 1,
          x: 0,
          y: 0,
          row: [
            {
              text: "上级物料编号：",
            },
            {
              text: "",
            },
            {
              text: "上级物料名称：",
            },
            {
              text: "",
            },
          ],
        },
        {
          type: 2,
          x: 0,
          y: 1,
          table: {
            header: [
              { text: "物料编号", prop: "f_number" },
              { text: "物料名称", prop: "f_name" },
              { text: "规格型号", prop: "f_model" },
              { text: "物料类别", prop: "f_type" },
              { text: "数量", prop: "f_count" },
              { text: "单位", prop: "f_unit" },
              { text: "物料属性", prop: "f_property" },
            ],
            data: [],
          },
        },
      ],
    };
  },
  methods: {
    async loadData(parent, queryData, isTree) {
      if (!this.treeChildMap[parent.f_MaterialId] || queryData.f_PId == "0") {
        const data = (await this.$awaitWraper(api.getList(queryData))) || [];
        data.forEach((item) => {
          item.leaf = item.chlidNum == 0;
          item.hasChildren = item.chlidNum > 0;
          item.id = this.$uuid();
        });
        console.log(data);
        this.treeChildMap[queryData.f_PId] = data;
      }

      if (parent) {
        this.treeMap[queryData.f_PId] = this.treeMap[queryData.f_PId] || [];
        if (this.treeMap[queryData.f_PId].indexOf(parent.f_Id) == -1) {
          this.treeMap[queryData.f_PId].push(parent.f_Id);
        }
      }

      if (isTree) {
        const res = this.$deepClone(this.treeChildMap[queryData.f_PId]);
        res.forEach((item) => {
          item.id = this.$uuid();
          this.treeMap[item.f_Id] = this.treeMap[item.f_Id] || [];
          this.treeMap[item.f_Id].push(item.id);
        });
        return res;
      } else {
        return this.treeChildMap[queryData.f_PId];
      }
    },

    async loadNode(node, resolve) {
      let queryData = {};
      if (node.level == 0) {
        queryData.f_PId = "0";
        queryData.f_Name = this.searchWord;
      } else {
        queryData.f_PId = node.data.f_MaterialId;
      }

      const res = await this.loadData(node.data, queryData, true);
      if (node.data) {
        node.data.children = res;
      }

      if (
        node.data &&
        this.currentTableData.length > 0 &&
        this.currentTableData[0].f_MaterialId == node.data.f_MaterialId
      ) {
        this.tableData = res;
      }

      resolve(res);
    },
    async loadTreeTable(row, treeNode, resolve) {
      let queryData = {};
      queryData.f_PId = row.f_MaterialId;
      const res = await this.loadData(row, queryData);
      resolve(res);
    },

    deleteTreeOne(fid) {
      const ids = this.treeMap[fid] || [];
      let node = null;
      ids.forEach((id) => {
        if (node == null) {
          node = this.$refs.tree.getNode(id);
        }
        this.$refs.tree.remove(id);
      });
      if (node != null) {
        const children = this.treeChildMap[node.data.f_PId] || [];
        const index = children.findIndex((t) => t.f_Id == fid);
        if (index > -1) {
          children.splice(index, 1);
        }
      }
    },
    addTree(res) {
      res.leaf = res.chlidNum == 0;
      res.hasChildren = res.chlidNum > 0;
      this.treeChildMap[res.f_PId].push(res);
      if (res.f_PId == "0") {
        res.id = this.$uuid();
        this.treeMap[res.f_Id] = this.treeMap[res.f_Id] || [];
        this.treeMap[res.f_Id].push(res.id);
        this.data.push(res);
      } else {
        const pidsList = this.treeMap[res.f_PId] || [];
        pidsList.forEach((pid) => {
          const ids = this.treeMap[pid] || [];
          ids.forEach((id) => {
            const nData = this.$deepClone(res);
            nData.id = this.$uuid();
            this.treeMap[nData.f_Id] = this.treeMap[nData.f_Id] || [];
            this.treeMap[nData.f_Id].push(nData.id);
            this.$refs.tree.append(nData, id);
          });
        });
      }
    },
    async updateTree(res) {
      res.leaf = res.chlidNum == 0;
      res.hasChildren = res.chlidNum > 0;

      const ids = this.treeMap[res.f_Id] || [];
      let pid = res.f_PId;
      ids.forEach((id) => {
        const node = this.$refs.tree.getNode(id);
        if (node) {
          const nData = this.$deepClone(res);
          nData.id = id;
          node.data = nData;

          const pnode = node.parent;
          var index = pnode.data.children.findIndex((t) => t.id == res.id);
          pnode.data.children[index] = nData;
        }
      });

      if (res.f_Id == this.currentTableData[0].f_Id) {
        await this.handleNodeClick(res);
      }

      const children = this.treeChildMap[pid] || [];
      const index2 = children.findIndex((t) => t.f_Id == res.f_Id);
      if (index2 > -1) {
        children[index2] = res;
      }
    },

    handleSearch() {
      this.isTree = false;
      this.$nextTick(() => {
        this.isTree = true;
      });
    },

    async handleNodeClick(data) {
      let queryData = {};
      queryData.f_PId = data.f_MaterialId;
      this.tableData = await this.loadData(data, queryData);
      this.currentTableData = [data];
    },

    handleAdd(isChild) {
      this.formIsChild = isChild;
      if (isChild) {
        this.formPid = this.currentTableData[0].f_MaterialId;
      } else {
        this.formPid = "0";
      }
      this.formEdit = false;
      this.handleShowForm(isChild ? "Add子级物料" : "Add1级BOM");
    },
    handleEdit($index, row) {
      this.formIsChild = false;
      this.formEdit = true;
      this.formEditRow = row;
      this.handleShowForm("Edit");
    },
    handleSonEdit($index, row) {
      this.formIsChild = true;
      this.formEdit = true;
      this.formEditRow = row;
      this.handleShowForm("子级物料Edit");
    },
    handleDelete($index, row) {
      this.$confirm(
        this.$t("This operation will permanently delete the data. Do you want to continue?"),
        this.$t("Tips"),
        {
          confirmButtonText: this.$t("confirm"),
          cancelButtonText: this.$t("cancel"),
          type: "warning",
        }
      )
        .then(async () => {
          await api.remove(row.f_Id);
          this.$message({
            type: "success",
            message: this.$t("Delete  success"),
          });
          this.currentTableData = [];
          this.tableData = [];
          this.deleteTreeOne(row.f_Id);
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: this.$t("Delete has been canceled!"),
          });
        });
    },
    handleSonDelete($index, row) {
      this.$confirm(
        this.$t("This operation will permanently delete the data. Do you want to continue?"),
        this.$t("Tips"),
        {
          confirmButtonText: this.$t("confirm"),
          cancelButtonText: this.$t("cancel"),
          type: "warning",
        }
      )
        .then(async () => {
          await api.remove(row.f_Id);
          this.$message({
            type: "success",
            message: this.$t("Delete  success"),
          });
          this.deleteTreeOne(row.f_Id);
        })
        .catch((error) => {
          console.log(error, "handleSonDelete");
          this.$message({
            type: "info",
            message: this.$t("Delete has been canceled!"),
          });
        });
    },

    async handleSave(showLoading, hideLoading) {
      showLoading("saving data...");
      if (await this.$refs.form.validateForm()) {
        const res = await this.$refs.form.saveForm({
          keyValue: this.formEdit ? this.formEditRow.f_Id : "",
          isEdit: this.formEdit,
        });
        if (res) {
          if (this.formEdit) {
            await this.updateTree(res);
          } else {
            this.addTree(res);
          }

          const msg = this.formEdit ? "更新成功!" : "Add成功!";
          this.$message({
            type: "success",
            message: this.$t(msg),
          });

          this.formVisible = false;
        }
      }
      hideLoading();
    },

    handleShowForm(text) {
      this.formTitle = text;
      this.formVisible = true;
    },
    async handleOpenedForm(showLoading, hideLoading) {
      if (this.formEdit) {
        showLoading("Loading data...");
        await this.$refs.form.loadFormData({ keyValue: this.formEditRow.f_Id });
        hideLoading();
      }
    },
    handleCloseForm() {
      this.$refs.form.resetForm();
    },

    // 导入产品
    importProduct() {
      this.excelImportVisible = true;
    },
    // 导出产品
    exportProduct() {
      this.lr_downFile("erpCase/bom/excel/export", "BOM导出");
      //erpCase/bom/excel/export
    },
  },
};
</script>

<style lang="scss">
.learun-bom-page {
  .l-panel--tool {
    border-bottom: 0;
  }

  .l-layout--wrapper {
    .l-panel--warpper {
      border-radius: 0 0 2px 2px;
    }
  }

  .l-layout--left,
  .l-layout--top,
  .l-layout--wrapper {
    .l-panel--warpper {
      border: 1px solid #d9d9d9;
    }

    .l-panel--title {
      font-size: 14px;
    }
  }
  .l-layout--left {
    .l-panel--warpper {
      border-radius: 2px;
    }

    .el-button {
      width: 95px;
      padding: 7px 0 !important;
    }
  }
  .l-layout--top {
    padding-bottom: 0;
  }

  .l-layout--top {
    .l-panel--title {
      font-size: 14px;
    }
    .l-panel--warpper {
      border-radius: 2px 2px 0 0;
      border-bottom: 0;
    }
  }
}
</style>
